﻿using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Yyd.OfficeFile.Excel
{
    public static class ListExcel
    {
        private const int MaxRowCount = 65000;

        private const int MaxTotalCount = 100000;

        private const int defaultColumnWidth = 5000;
        private const int defaultRowHeight = 300;

        /// <summary>
        /// 导出List数据到Excel
        /// </summary>
        /// <typeparam name="TSource">List</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="sheetName">Excel-SheetName名称</param>
        /// <param name="headArray">首行标题</param>
        /// <returns>内存文件流</returns>
        public static MemoryStream Export<TSource>(this IEnumerable<TSource> source,
            string[] headArray = null, string[] ignoreArray = null, Action<ISheet> actionSheet = null) where TSource : class
        {

            if (ignoreArray == null || ignoreArray?.Length == 0)
                ignoreArray = new[] { "Id" };


            if (source == null || source.Count() == 0) return ThrowNewUserFriendlyException("您导出的数据源是空的");
            if (source.Count() > MaxTotalCount) return ThrowNewUserFriendlyException("每次最多只能导出10万条数据");

            var t = source?.First()?.GetType();
            if (!t.IsClass || t.GetProperties().Length == 0) return new MemoryStream();
            string sheetName = "sheet";

            HSSFWorkbook workbook = new HSSFWorkbook();
            MemoryStream ms = new MemoryStream();

            int Count = (source?.Count() ?? 0) / MaxRowCount;
            for (int i = 0; i <= Count; i++)
            {
                ISheet sheet = workbook.CreateSheet(sheetName + i.ToString());

            }
            for (int i = 0; i <= Count; i++)
            {

                ISheet sheet = workbook.GetSheet(sheetName + i.ToString());

                ICellStyle style = workbook.CreateCellStyle();
                var font = workbook.CreateFont();
                //font.IsBold = true;
                style.SetFont(font);
                style.VerticalAlignment = VerticalAlignment.Center;
                style.Alignment = HorizontalAlignment.Center;
                IRow headerRow = sheet.CreateRow(0);
                headerRow.Height = defaultRowHeight;
                var pros = t.GetProperties().Where(c => !ignoreArray.Contains(c.Name)).ToArray();

                // 表格头部 
                if (headArray != null && headArray.Length > 0)
                {
                    for (int h = 0; h < headArray.Length; h++)
                    { headerRow.CreateCell(h).SetCellValue(headArray[h]); headerRow.Cells[h].CellStyle = style; }
                }
                else
                {
                    for (int h = 0; h < pros.Length; h++)
                    {
                        headerRow.CreateCell(h).SetCellValue(pros[h].Name); headerRow.Cells[h].CellStyle = style;
                    }
                }

                int rowIndex = 1;
                for (int j = MaxRowCount * i; j < MaxRowCount * (i + 1); j++)
                {
                    if (j >= source?.Count() || rowIndex > MaxRowCount)
                        break;

                    IRow dataRow = sheet.CreateRow(rowIndex);
                    dataRow.Height = defaultRowHeight;
                    for (int m = 0; m < pros?.Length; m++)
                    {

                        var s = pros[m].GetValue(source.ElementAt(j))?.ToString();
                        dataRow.CreateCell(m).SetCellValue(s);
                       
                        sheet.SetColumnWidth(m, defaultColumnWidth);
                    }
                    rowIndex++;
                }
                if (actionSheet != null)
                {
                    actionSheet.Invoke(sheet);
                }
            }
            workbook.Write(ms);
            return ms;
        }

        private static MemoryStream ThrowNewUserFriendlyException(string msg)
        {

            MemoryStream ms = new MemoryStream();
            HSSFWorkbook workbook = new HSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("提示");
            IRow headerRow = sheet.CreateRow(0);

            headerRow.CreateCell(0).SetCellValue(msg);
            workbook.Write(ms);
            return ms;

        }
    }
}
